package net.es.weathermap.metric;

import java.text.ParseException;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;

import org.apache.log4j.Logger;
import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.SchedulerException;

import net.es.weathermap.beans.Domain;
import net.es.weathermap.beans.Path;
import net.es.weathermap.path.idc.IDCPathProvider;
import net.es.weathermap.sched.FetchOscarsMetricsJob;
import net.es.weathermap.sched.JobScheduler;

public class OscarsMP extends UtilizationMP implements MetricProvider {
    private static Logger LOG = Logger.getLogger(OscarsMP.class);
    private MetricCache mc;
    protected static OscarsMP instance;

    protected MetricCache getCache() {
        return mc;
    }

    private OscarsMP(Domain dom) {
        if (mc == null) {
            mc = new MetricCache();
            // 1 hour
            mc.setTimeout(3600000L);
        }
        domain = dom;
        this.initNameMaps();

        // fetch
        try {
            this.fetchValues(null);
        } catch (Exception e2) {
            // TODO Auto-generated catch block
            e2.printStackTrace();
        }
        JobScheduler jsch = JobScheduler.getInstance();
        jsch.start();
        JobDetail jobDetail =
            new JobDetail("fom", "fom", FetchOscarsMetricsJob.class);
        CronTrigger trig = null;
        try {
            // get new OSCARS data every 1h
            // will likely
            trig = new CronTrigger("fom", "fom", "0 0 * * * ?");
            jsch.getScheduler().scheduleJob(jobDetail, trig);
        } catch (ParseException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        } catch (SchedulerException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public static OscarsMP getInstance(Domain dom) {
        if (instance == null) {
            instance = new OscarsMP(dom);
        }
        return instance;
    }

    public static OscarsMP getInstance() {
        return instance;
    }

    public synchronized HashMap<String, CacheEntry>
        fetchValues(List<String> identifiers) throws Exception {

        LOG.info("fetchOscarsValues.start");
        IDCPathProvider ip = IDCPathProvider.getInstance(domain);
        HashMap<String, CacheEntry> reservedIfces =
            new HashMap<String, CacheEntry>();
        List<Path> paths = ip.getPaths(domain);
        for (Path path : paths) {
            Double bw = path.getBandwidth().doubleValue();
            for (String hopIfceId : path.getHopIfces()) {
                // bad bad bad workaround
                hopIfceId = hopIfceId + ".0";
                HashMap<String, ArrayList<Double>> entry;
                if (reservedIfces.get(hopIfceId) == null) {
                    entry = new HashMap<String, ArrayList<Double>>();
                    ArrayList<Double> vals = new ArrayList<Double>();
                    vals.add(bw);
                    entry.put("in", vals);
                    CacheEntry ce = new CacheEntry();
                    ce.setEntry(entry);
                    reservedIfces.put(hopIfceId, ce);
                } else {
                    entry = reservedIfces.get(hopIfceId).getEntry();
                    ArrayList<Double> vals = entry.get("in");
                    vals.set(0, vals.get(0) + bw);
                    LOG.info(hopIfceId);
                }
            }
        }
        mc.clear();
        mc.cacheMetrics(reservedIfces);
        LOG.info("fetchOscarsValues: fetched and cached "+reservedIfces.size()+" values");
        return reservedIfces;
    }
}
